home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 1 / Gold Medal Software Volume 1 (Gold Medal) (1994).iso / graphics / tierra40.arj / TIERRA / INSTRUCT.C < prev    next >
C/C++ Source or Header  |  1992-09-09  |  46KB  |  1,532 lines

  1. /* instruct.c  9-9-92  instruction set for the Tierra Simulator */
  2. /* Tierra Simulator V4.0: Copyright (c) 1991, 1992 Tom Ray & Virtual Life */
  3.  
  4. #ifndef lint
  5. static char sccsid[] = "@(#)instruct.c    1.22     9/19/91";
  6. #endif
  7.  
  8. #include "license.h"
  9. #include "tierra.h"
  10. #include "extern.h"
  11.  
  12. #ifdef ALCOMM
  13. #include "tmonitor.h"
  14. #include "trequest.h"
  15. #endif /* ALCOMM */
  16.  
  17. #ifdef MEM_CHK
  18. #include <memcheck.h>
  19. #endif /* MEM_CHK */
  20.  
  21. /* takes no arguments, returns no values (except clears flag) */
  22. void nop(ce) /* no operation */
  23. Pcells  ce;
  24. {   ce->c.fl = 0; }
  25.  
  26. #if INST == 2
  27.  
  28. /* void regorder(ce) adjust register order
  29.  * is.sval  = the number of the register that will go to the top
  30.  */
  31. void regorder(ce) /* adjust register order */
  32. Pcells  ce;
  33. {   pushst(ce);
  34.     is.sval += flaw(ce);
  35.     ce->c.re[NUMREG] = mo(is.sval, NUMREG);
  36.     ce->c.fl = 0;
  37. }
  38.  
  39. void pushst(ce) /* called by regorder() */
  40. Pcells  ce;
  41. {   I16s  i;
  42.  
  43.     for (i = (2 * NUMREG) - 1; i > NUMREG; i--)
  44.         ce->c.re[i] = ce->c.re[i - 1];
  45. /*
  46.     ce->c.re[7] = ce->c.re[6];
  47.     ce->c.re[6] = ce->c.re[5];
  48.     ce->c.re[5] = ce->c.re[4];
  49. */
  50. }
  51.  
  52. #endif /* INST == 2 */
  53.  
  54. #if INST == 3
  55.  
  56. /* takes no arguments, returns no values (except clears flag) */
  57. void rollu(ce)
  58. Pcells  ce;
  59. {   I32s  tvar;
  60.     I16s  i;
  61.  
  62.     tvar = ce->c.re[i = NUMREG - 1] + flaw(ce);
  63.     for (; i > 0; i--)
  64.         ce->c.re[i] = ce->c.re[i - 1] + flaw(ce);
  65.     ce->c.re[0] = tvar;
  66.     ce->c.fl = 0;
  67. }
  68.  
  69. /* takes no arguments, returns no values (except clears flag) */
  70. void rolld(ce)
  71. Pcells  ce;
  72. {   I32s  tvar;
  73.     I16s  i;
  74.  
  75.     tvar = ce->c.re[0] + flaw(ce);
  76.     for (i = 0; i < NUMREG - 1; i++)
  77.         ce->c.re[i] = ce->c.re[i + 1] + flaw(ce);
  78.     ce->c.re[NUMREG - 1] = tvar;
  79.     ce->c.fl = 0;
  80. }
  81.  
  82. /* takes no arguments, returns no values (except clears flag) */
  83. void enter(ce)
  84. Pcells  ce;
  85. {   I32s  tvar;
  86.     I16s  i;
  87.  
  88.     for (i = NUMREG - 1; i > 0; i--)
  89.         ce->c.re[i] = ce->c.re[i - 1] + flaw(ce);
  90.     ce->c.re[0] += flaw(ce);
  91.     ce->c.fl = 0;
  92. }
  93.  
  94. /* takes no arguments, returns no values (except clears flag) */
  95. void exch(ce)
  96. Pcells  ce;
  97. {   I32s  tvar;
  98.  
  99.     tvar = ce->c.re[0] + flaw(ce);
  100.     ce->c.re[0] = ce->c.re[1] + flaw(ce);
  101.     ce->c.re[1] = tvar;
  102.     ce->c.fl = 0;
  103. }
  104.  
  105. /* void math3(ce) *(is.dreg) = is.sval + is.sval2 + flaw(ce);
  106.  * is.dreg  = destination register, where calculation will be stored
  107.  * is.sval  = a value that will be added to is.sval2 and placed in dest reg
  108.  * is.sval2 = a value that will be added to is.sval  and placed in dest reg
  109.  * is.dmod  = value by which to modulus destination register
  110.  * is.dran  = range within which to contain destination register
  111.  */
  112. void math3(ce) /* add two numbers and store them in a register, shift down */
  113. Pcells  ce;
  114. {   I16s  i;
  115.  
  116.     math(ce);
  117.     for (i = 1; i < NUMREG - 1; i++)
  118.         ce->c.re[i] = ce->c.re[i + 1] + flaw(ce);
  119. }
  120.  
  121. void pop3(ce)
  122. Pcells  ce;
  123. {   I16s  i;
  124.  
  125.     for (i = NUMREG - 1; i > 0; i--)
  126.         ce->c.re[i] = ce->c.re[i - 1] + flaw(ce);
  127.     pop(ce);
  128. }
  129.  
  130. /* void movdd3(ce) *(is.dreg) = is.sval + flaw(ce);
  131.  * is.dreg = destination register, where moved value will be placed
  132.  * is.sval = value to be placed in the dest reg
  133.  * is.dmod = value by which to modulus destination register
  134.  * is.dran = range within which to contain destination register
  135.  */
  136. void movdd3(ce) /* inter-register mov, and push up stack */
  137. Pcells  ce;
  138. {   I16s  i;
  139.  
  140.     for (i = NUMREG - 1; i > 0; i--)
  141.         ce->c.re[i] = ce->c.re[i - 1] + flaw(ce);
  142.     movdd(ce);
  143. }
  144.  
  145. void adr3(ce) /* find address of a template */
  146. Pcells  ce;
  147. {   I32s  tval;
  148.  
  149.     if (!is.sval2)
  150.     {   *(is.dreg) = is.sval;   /* source template missing */
  151. /*      SetFlag(ce); */
  152.         return;
  153.     }
  154.     tval = 3 + flaw(ce);
  155.     ce->c.re[mo(tval, NUMREG)] = ce->c.re[0] + flaw(ce);
  156.     adr(ce);
  157. }
  158.  
  159. void malchm3(ce)
  160. Pcells  ce;
  161. {   I16s  i;
  162.  
  163.     for (i = NUMREG - 1; i > 0; i--)
  164.         ce->c.re[i] = ce->c.re[i - 1] + flaw(ce);
  165.     malchm(ce);
  166. }
  167.  
  168. #endif /* INST == 3 */
  169.  
  170. #if INST != 1
  171.  
  172. /* void not(ce) *(is.dreg) = ~(is.sval) + flaw(ce);
  173.  * is.dreg = destination register
  174.  * is.sval = value whose bits will be flipped and put in dest reg
  175.  * is.dmod = value by which to modulus destination register
  176.  * is.dran = range within which to contain destination register
  177.  */
  178. void not(ce) /* flip all bits of destination register */
  179. Pcells  ce;
  180. {   *(is.dreg) = ~(is.sval) + flaw(ce);
  181.     if (is.dmod)
  182.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  183.         is.dmod = 0;
  184.     }
  185.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  186.     {   *(is.dreg) = 0;
  187.         is.dran = 0;
  188.     }
  189.     ce->c.fl = 0;
  190. }
  191.  
  192. /* void put(ce) write a value to the output buffer
  193.  * ce->c.pb[PUTBUFSIZ]     == pointer to next output value to be written
  194.  * ce->c.pb[PUTBUFSIZ + 1] == pointer to next output value to be read
  195.  * ce->c.pb[PUTBUFSIZ + 2] == number of unread output values
  196.  *
  197.  * is.dcel  = destination cell, in whose buffer the value will be put
  198.  * is.dreg  = destination "register" in the put buffer
  199.  * is.dval3 = destination for address returned by adr()
  200.  * is.mode3 = #ifdef ICC:  0 = broadcast to other cells' get buffer
  201.  *                         1 = write to other cell's get buffer
  202.  *            #ifndef ICC: write to own put buffer (prayer)
  203.  *
  204.  * #ifndef ICC specify the values used by movdd():
  205.  * is.dreg = destination register, where moved value will be placed
  206.  * is.sval = value to be placed in the dest reg
  207.  * is.dmod = value by which to modulus destination register
  208.  * is.dran = range within which to contain destination register
  209.  *
  210.  * #ifdef ICC specify the values used by adr():
  211.  * void adr(ce) find address of a template
  212.  * is.mode  = search mode: 1 = forward, 2 = backward, 0 = outward
  213.  * is.mode2 =  preference: 1 = forward, 2 = backward, and return for
  214.  *        direction found: 1 = forward, 2 = backward, 3 = both, 0 = none
  215.  * is.dval  = starting address for forward search
  216.  * is.dval2 = starting address for backward search
  217.  * is.dreg  = destination register where target address will be stored
  218.  * is.dreg2 = destination register where template size will be stored
  219.  * is.dreg3 = destination register where offset of target will be stored
  220.  * is.sval  = return address if template size = 0
  221.  * is.sval2 = template size, 0 = no template
  222.  * is.sval3 = search limit, and return for distance actually searched
  223.  * is.dmod  = modulus value for is.dreg
  224.  * is.dmod2 = modulus value for is.dreg2
  225.  * is.dmod3 = modulus value for is.dreg3
  226.  * is.dran  = range to maintain for is.dreg
  227.  * is.dran2 = range to maintain for is.dreg2
  228.  * is.dran3 = range to maintain for is.dreg3
  229.  */
  230. void put(ce) /* write a value to the output buffer */
  231. Pcells  ce;
  232. {   Pcells  dc = is.dcel;
  233.     I32s    ta, lpl = Put_limit;
  234.     I8s     tmode2 = is.mode2, md;
  235.  
  236.     if (is.dreg == &BitBucket)
  237.     {   SetFlag(ce);
  238.         return;
  239.     }
  240. #ifdef ICC
  241.  
  242.     if (is.mode3) /* write to other cell's get buffer */
  243.         Write2Get(dc, is.sval);
  244.     else
  245.     {   adr(ce);
  246.         if (!ce->c.fl) do /* broadcast to other cells' get buffer */
  247.         {   if (is.mode2 == 1 || is.mode2 == 3)
  248.             {   ta = is.dval - 1;
  249.                 if (is.dcel = FindPutCell(ad(ta)))
  250.                 {   Write2Get(is.dcel, is.sval);
  251.                 }
  252.             }
  253.             if (is.mode2 == 2 || is.mode2 == 3)
  254.             {   ta = is.dval2 - 1;
  255.                 if (is.dcel = FindPutCell(ad(ta)))
  256.                 {   Write2Get(is.dcel, is.sval);
  257.                 }
  258.             }
  259.             is.mode2 = tmode2;
  260.             lpl -= is.sval3;
  261.             is.sval3 = lpl;
  262.             is.dval++; is.dval2--;
  263.             adr(ce);
  264.         } while (!ce->c.fl);
  265.     }
  266.  
  267. #else  /* ICC */         /* write to own put buffer */
  268.  
  269.     movdd(ce);
  270.     ce->c.pb[PUTBUFSIZ] = ++(ce->c.pb[PUTBUFSIZ]) % PUTBUFSIZ;
  271.     ce->c.pb[PUTBUFSIZ + 2] =
  272.         1 + ((++(ce->c.pb[PUTBUFSIZ + 2]) - 1) % PUTBUFSIZ);
  273.  
  274. #endif /* ICC */
  275.     ce->c.fl = 0;
  276. }
  277.  
  278. Pcells FindPutCell(adre)
  279. I32s  adre;
  280. {   Pcells  ce;
  281.     I8s     md;
  282.  
  283. #if PLOIDY == 1
  284.     if(strcmp(id[soup[adre].inst].mn, "get")
  285. #else /* PLOIDY > 1 */
  286.     if(strcmp(id[soup[adre][ce->d.tr].inst].mn, "get")
  287. #endif /* PLOIDY > 1 */
  288.         || adre < 0 || adre >= SoupSize || IsFree(adre))
  289.         ce = NULL;
  290.     else
  291.     {   WhichCell(adre, &ce, &md);
  292. /*      if (md == 'd')
  293.             ce = NULL;
  294. */
  295.     }
  296.     return ce;
  297. }
  298.  
  299. I8s ReadFPut(ce, value) /* for god to read the data in the output buffer */
  300. Pcells  ce;
  301. I32s    *value;
  302. {   if (ce->c.pb[PUTBUFSIZ + 2])
  303.     {   *value = ce->c.pb[ce->c.pb[PUTBUFSIZ + 1]];
  304.         --(ce->c.pb[PUTBUFSIZ + 2]);
  305.         ce->c.pb[PUTBUFSIZ + 1] = ++(ce->c.pb[PUTBUFSIZ + 1]) % PUTBUFSIZ;
  306.         return 1;
  307.     }
  308.     return 0;
  309. }
  310.  
  311. /* void get(ce) read a value from the input buffer
  312.  * ce->c.gb[GETBUFSIZ]     == pointer to next input value to be read
  313.  * ce->c.gb[GETBUFSIZ + 1] == pointer to next input value to be written
  314.  * ce->c.gb[GETBUFSIZ + 2] == number of unread input values
  315.  *
  316.  * also specify the values used by movdd():
  317.  * is.dreg = destination register, where moved value will be placed
  318.  * is.sval = value to be placed in the dest reg
  319.  * is.dmod = value by which to modulus destination register
  320.  * is.dran = range within which to contain destination register
  321.  */
  322. void get(ce) /* read a value from the input buffer */
  323. Pcells  ce;
  324. {   if (ce->c.gb[GETBUFSIZ + 2])
  325.     {   movdd(ce);
  326.         --(ce->c.gb[GETBUFSIZ + 2]);
  327.         ce->c.gb[GETBUFSIZ] = ++(ce->c.gb[GETBUFSIZ]) % GETBUFSIZ;
  328.     }
  329.     ce->c.fl = 0;
  330. }
  331.  
  332. void Write2Get(ce, value) /* place value in input buffer of cell ce */
  333. Pcells  ce;
  334. I32s    value;
  335. {   ce->c.gb[ce->c.gb[GETBUFSIZ + 1]] = value;
  336.     ce->c.gb[GETBUFSIZ + 1] = ++(ce->c.gb[GETBUFSIZ + 1]) % GETBUFSIZ;
  337.     ce->c.gb[GETBUFSIZ + 2] =
  338.         1 + ((++(ce->c.gb[GETBUFSIZ + 2]) - 1) % GETBUFSIZ);
  339. }
  340.  
  341. void Broad2Get(value) /* broadcast value to input buffer of all cells */
  342. I32s  value;
  343. {   Pcells  ce = ThisSlice;
  344.  
  345.     do
  346.     {   Write2Get(ce, value);
  347.         ce = &cells[ce->q.n_time.a][ce->q.n_time.i];
  348.     } while (ce != ThisSlice);
  349. }
  350.     
  351. #endif /* INST != 1 */
  352.  
  353. /* void not0(ce) *(is.dreg) ^= (1 + flaw(ce));
  354.  * is.dreg = destination register, whose bit will be flipped
  355.  * is.dmod = value by which to modulus destination register
  356.  * is.dran = range within which to contain destination register
  357.  */
  358. void not0(ce) /* flip low order bit of destination register */
  359. Pcells  ce;
  360. {   *(is.dreg) ^= (1 + flaw(ce));
  361.     if (is.dmod)
  362.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  363.         is.dmod = 0;
  364.     }
  365.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  366.     {   *(is.dreg) = 0;
  367.         is.dran = 0;
  368.     }
  369.     ce->c.fl = 0;
  370. }
  371.  
  372. /* void shl(ce) *(is.dreg) <<= (Reg) (1 + flaw(ce));
  373.  * is.dreg = destination register, whose bits will be shifted left
  374.  * is.dmod = value by which to modulus destination register
  375.  * is.dran = range within which to contain destination register
  376.  */
  377. void shl(ce) /* shift left all bits in register */
  378. Pcells  ce;
  379. {   *(is.dreg) <<= (Reg) (1 + flaw(ce));
  380.     if (is.dmod)
  381.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  382.         is.dmod = 0;
  383.     }
  384.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  385.     {   *(is.dreg) = 0;
  386.         is.dran = 0;
  387.     }
  388.     ce->c.fl = 0;
  389. }
  390.  
  391. /* void ifz(ce) if (is.sval + flaw(ce)) is.iip = is.sval2;
  392.  * is.sval  = value to test for zero
  393.  * is.sval2 = amount to increment IP if is.sval == 0
  394.  * is.iip   = amount to increment IP if is.sval != 0
  395.  */
  396. void ifz(ce) /* execute or skip next instruction, if is.sval == 0 */
  397. Pcells  ce;
  398. {   if (is.sval + flaw(ce)) /* is.sval2 = 2 to skip next instruction */
  399.         is.iip = is.sval2;  /* is.sval2 = 1 to execute next instruction */
  400.     ce->c.fl = 0;
  401. }
  402.  
  403. /* void math(ce) *(is.dreg) = is.sval + is.sval2 + flaw(ce);
  404.  * is.dreg  = destination register, where calculation will be stored
  405.  * is.sval  = a value that will be added to is.sval2 and placed in dest reg
  406.  * is.sval2 = a value that will be added to is.sval  and placed in dest reg
  407.  * is.dmod  = value by which to modulus destination register
  408.  * is.dran  = range within which to contain destination register
  409.  */
  410. void math(ce) /* add two numbers and store them in a register */
  411. Pcells  ce;
  412. {   *(is.dreg) = is.sval + is.sval2 + flaw(ce);
  413.     if (is.dmod)
  414.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  415.         is.dmod = 0;
  416.     }
  417.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  418.     {   *(is.dreg) = 0;
  419.         is.dran = 0;
  420.     }
  421.     ce->c.fl = 0;
  422. }
  423.  
  424. /* void push(ce) ce->c.sp = ++ce->c.sp % STACK_SIZE;
  425.  *               ce->c.st[ce->c.sp] = is.sval + flaw(ce);
  426.  * is.sval = value to be pushed onto the stack
  427.  */
  428. void push(ce) /* push a value onto the stack */
  429. Pcells  ce;
  430. {   ce->c.sp = ++ce->c.sp % STACK_SIZE;
  431.     ce->c.st[ce->c.sp] = is.sval + flaw(ce);
  432.     ce->c.fl = 0;
  433. }
  434.  
  435. /* void pop(ce) *(is.dreg) = ce->c.st[ce->c.sp] + flaw(ce);
  436.  *              if (!ce->c.sp) ce->c.sp = STACK_SIZE - 1; else --ce->c.sp;
  437.  * is.dreg = destination register, where value popped off stack will go
  438.  * is.dmod = value by which to modulus destination register
  439.  * is.dran = range within which to contain destination register
  440.  */
  441. void pop(ce) /* pop a value from the stack into a register */
  442. Pcells  ce;
  443. {   *(is.dreg) = ce->c.st[ce->c.sp] + flaw(ce);
  444.     if (!ce->c.sp) ce->c.sp = STACK_SIZE - 1; /* decrement stack pointer */
  445.     else --ce->c.sp;
  446.     if (is.dmod)
  447.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  448.         is.dmod = 0;
  449.     }
  450.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  451.     {   *(is.dreg) = 0;
  452.         is.dran = 0;
  453.     }
  454.     ce->c.fl = 0;
  455. }
  456.  
  457. /* void adr(ce) find address of a template
  458.  * is.mode  = search mode: 1 = forward, 2 = backward, 0 = outward
  459.  * is.mode2 =  preference: 1 = forward, 2 = backward, and return for
  460.  *        direction found: 1 = forward, 2 = backward, 3 = both, 0 = none
  461.  * is.dval  = starting address for forward search
  462.  * is.dval2 = starting address for backward search
  463.  * is.dreg  = destination register where target address will be stored
  464.  * is.dreg2 = destination register where template size will be stored
  465.  * is.dreg3 = destination register where offset of target will be stored
  466.  * is.sval  = return address if template size = 0
  467.  * is.sval2 = template size, 0 = no template
  468.  * is.sval3 = search limit, and return for distance actually searched
  469.  * is.dmod  = modulus value for is.dreg
  470.  * is.dmod2 = modulus value for is.dreg2
  471.  * is.dmod3 = modulus value for is.dreg3
  472.  * is.dran  = range to maintain for is.dreg
  473.  * is.dran2 = range to maintain for is.dreg2
  474.  * is.dran3 = range to maintain for is.dreg3
  475.  */
  476. /* void push(ce)
  477.  * is.sval = value to be pushed onto the stack
  478.  */
  479. void tcall(ce) /* call template */
  480. Pcells  ce;
  481. {   adr(ce);
  482.     push(ce);
  483. }
  484.  
  485. /* specify the values used by movdd():
  486.  * is.dreg = destination register, where moved value will be placed
  487.  * is.sval = value to be placed in the dest reg
  488.  * is.dmod = value by which to modulus destination register
  489.  * is.dran = range within which to contain destination register
  490.  */
  491. /* void push(ce)
  492.  * is.sval = value to be pushed onto the stack
  493.  */
  494. void call(ce) /* call address */
  495. Pcells  ce;
  496. {   movdd(ce);
  497.     push(ce);
  498. }
  499.  
  500. /* void mov(ce) move some data
  501.  * is.mode = form of mov to use
  502.  * see specific movs below for other passed values
  503.  */
  504. void mov(ce) /* move some data */
  505. Pcells  ce;
  506. {   switch (is.mode)
  507.     {   case 0: movdd(ce); break; /*   direct destination,   direct source */
  508.         case 1: movdi(ce); break; /*   direct destination, indirect source */
  509.         case 2: movid(ce); break; /* indirect destination,   direct source */
  510.         case 3: movii(ce); break; /* indirect destination, indirect source */
  511.     }
  512. }
  513.  
  514. /* void movdd(ce) *(is.dreg) = is.sval + flaw(ce);
  515.  * is.dreg = destination register, where moved value will be placed
  516.  * is.sval = value to be placed in the dest reg
  517.  * is.dmod = value by which to modulus destination register
  518.  * is.dran = range within which to contain destination register
  519.  */
  520. void movdd(ce) /* inter-register mov */
  521. Pcells  ce;
  522. {   *(is.dreg) = is.sval + flaw(ce);
  523.     if (is.dmod)
  524.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  525.         is.dmod = 0;
  526.     }
  527.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  528.     {   *(is.dreg) = 0;
  529.         is.dran = 0;
  530.     }
  531.     ce->c.fl = 0;
  532. }
  533.  
  534. /* void movdi(ce) is.dins->inst = is.sval + flaw(ce);
  535.  * is.dval  = address of destination instruction
  536.  * is.dins  = pointer to destination instruction
  537.  * is.sval  = value to be moved to destination instruction
  538.  * is.sval2 = original value of destination instruction
  539.  */
  540. void movdi(ce) /* move from register to soup, e.g.: soup [R0] = R1 */
  541. Pcells  ce;
  542. {   if ((0 <= is.dval && is.dval < SoupSize)
  543. #ifdef WRITEPROT
  544.         && (!is.dins->write || IsInsideCell(ce, is.dval))
  545. #endif /* WRITEPROT */
  546.         )
  547.     {   is.dins->inst = is.sval + flaw(ce);
  548.         ce->c.fl = 0;
  549.         if (is.dval >= ce->md.p && is.dval < ce->md.p + ce->md.s)
  550.             ce->d.mov_daught++;
  551.         else if (is.dins->inst != is.sval2)
  552.             MutBookeep(is.dval);
  553.     }
  554.     else SetFlag(ce);
  555. }
  556.  
  557. /* void movid(ce) *(is.dreg) = is.sins->inst + flaw(ce);
  558.  * is.sins = pointer to source instruction
  559.  * is.sval = address of source instruction
  560.  * is.dreg = destination register, where moved value will be placed
  561.  * is.dmod = value by which to modulus destination register
  562.  * is.dran = range within which to contain destination register
  563.  */
  564. void movid(ce) /* move from soup to register, e.g.: R0 = soup [R1] */
  565. Pcells  ce;
  566. {
  567. #ifdef READPROT
  568.     if (!is.sins->read || IsInsideCell(ce, is.sval))
  569. #endif /* READPROT */
  570.     {   *(is.dreg) = is.sins->inst + flaw(ce);
  571.         ce->c.fl = 0;
  572.     }
  573. #ifdef READPROT
  574.     else
  575.     {   SetFlag(ce);
  576.         return;
  577.     }
  578. #endif /* READPROT */
  579.     if (is.dmod)
  580.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  581.         is.dmod = 0;
  582.     }
  583.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  584.     {   *(is.dreg) = 0;
  585.         is.dran = 0;
  586.     }
  587. }
  588.  
  589. /* void movii(ce) is.dins->inst = is.sins->inst;
  590.  * is.dval  = address of destination instruction
  591.  * is.dins  = pointer to destination instruction
  592.  * is.sval  = address of source instruction
  593.  * is.sins  = pointer to source instruction
  594.  * is.dtra  = track of destination instruction
  595.  * is.sval2 = original value of destination instruction
  596.  */
  597. void movii(ce) /* move data from soup to soup, e.g.: soup [R0] = soup [R1] */
  598. Pcells  ce;
  599. {   if ((is.dval != is.sval)
  600. #ifdef WRITEPROT
  601.         && (!is.dins->write || IsInsideCell(ce, is.dval))
  602. #endif /* WRITEPROT */
  603. #ifdef READPROT
  604.         && (!is.sins->read  || IsInsideCell(ce, is.sval))
  605. #endif /* READPROT */
  606.         && (0 <= is.dval && is.dval < SoupSize)
  607.         && (0 <= is.sval && is.sval < SoupSize))
  608.     {   is.dins->inst = is.sins->inst;
  609.         if (RateMovMut && ++CountMovMut >= RateMovMut)
  610.         {   mut_site(soup + ad(is.dval), is.dtra);
  611.             CountMovMut = tlrand() % RateMovMut;
  612.             TotMovMut++;
  613.         }
  614.         if (WatchMov) GenExMov(ce, is.dval, is.sval);
  615.         if (is.dval >= ce->md.p && is.dval < ce->md.p + ce->md.s)
  616.             ce->d.mov_daught++;
  617.         else if (is.dins->inst != is.sval2)
  618.             MutBookeep(is.dval);
  619.         ce->c.fl = 0;
  620. #ifdef ALCOMM
  621.         if ( MIsDFEnabled( TrtMVEvent ) )
  622.             TMoveD( ce->mm.p,is.sval,is.dval);
  623. #endif /* ALCOMM */
  624.     }
  625.     else SetFlag(ce);
  626. }
  627.  
  628. /* void adr(ce) find address of a template
  629.  * is.mode  = search mode: 1 = forward, 2 = backward, 0 = outward
  630.  * is.mode2 =  preference: 1 = forward, 2 = backward, and return for
  631.  *        direction found: 1 = forward, 2 = backward, 3 = both, 0 = none
  632.  * is.dval  = starting address for forward search
  633.  *                and return for finish address
  634.  * is.dval2 = starting address for backward search
  635.  *                and return for finish address
  636.  * is.dreg  = destination register where target address will be stored
  637.  * is.dreg2 = destination register where template size will be stored
  638.  * is.dreg3 = destination register where offset of target will be stored
  639.  * is.sval  = return address if template size = 0
  640.  * is.sval2 = template size, 0 = no template
  641.  * is.sval3 = search limit, and return for distance actually searched
  642.  * is.dmod  = modulus value for is.dreg
  643.  * is.dmod2 = modulus value for is.dreg2
  644.  * is.dmod3 = modulus value for is.dreg3
  645.  * is.dran  = range to maintain for is.dreg
  646.  * is.dran2 = range to maintain for is.dreg2
  647.  * is.dran3 = range to maintain for is.dreg3
  648.  */
  649. void adr(ce) /* find address of a template */
  650. Pcells  ce;
  651. {   I32s adrt;
  652.  
  653.     if (!is.sval2)
  654.     {   *(is.dreg) = is.sval;   /* source template missing */
  655. /*      SetFlag(ce); */
  656.         return;
  657.     }
  658.     if (!is.mode)                 /* outward search */
  659.         adrt = ctemplate(&is.dval, &is.dval2, &is.sval3, &is.mode2, is.sval2,
  660.             'o', ce);
  661.     else if (is.mode == 1)        /* forward search */
  662.         adrt = ctemplate(&is.dval, &is.dval2, &is.sval3, &is.mode2, is.sval2,
  663.             'f', ce);
  664.     else if (is.mode == 2)        /* backward search */
  665.         adrt = ctemplate(&is.dval, &is.dval2, &is.sval3, &is.mode2, is.sval2,
  666.             'b', ce);
  667.     if (adrt < 0)                 /* target template not found */
  668.     {   is.iip = is.sval2 + 1;    /* skip IP over source template */
  669.         SetFlag(ce);
  670.         return;
  671.     }
  672.  
  673.     *(is.dreg3) = is.sval3;
  674.     if (is.dmod3)
  675.     {   *(is.dreg3) = mo(*(is.dreg3), is.dmod3);
  676.         is.dmod3 = 0;
  677.     }
  678.     else if (is.dran3 && (*(is.dreg3) > is.dran3 || *(is.dreg3) < -is.dran3))
  679.     {   *(is.dreg3) = 0;
  680.         is.dran3 = 0;
  681.     }
  682.  
  683.     *(is.dreg2) = is.sval2;
  684.     if (is.dmod2)
  685.     {   *(is.dreg2) = mo(*(is.dreg2), is.dmod2);
  686.         is.dmod2 = 0;
  687.     }
  688.     else if (is.dran2 && (*(is.dreg2) > is.dran2 || *(is.dreg2) < -is.dran2))
  689.     {   *(is.dreg2) = 0;
  690.         is.dran2 = 0;
  691.     }
  692.  
  693.     *(is.dreg) = adrt;
  694.     if (is.dmod)
  695.     {   *(is.dreg) = mo(*(is.dreg), is.dmod);
  696.         is.dmod = 0;
  697.     }
  698.     else if (is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
  699.     {   *(is.dreg) = 0;
  700.         is.dran = 0;
  701.     }
  702.  
  703.     ce->c.fl = 0;
  704.     return;
  705. }
  706.  
  707. /* void malchm(ce) allocate space and protect it
  708.  * is.dreg  = destination register where allocated address is stored
  709.  * is.sval  = requested size of block for mal()
  710.  * is.sval2 = flawed size of block
  711.  * is.sval3 = suggested address, and allocated address
  712.  * is.mode  = memory protection mode (rwx), probably MemModeProt
  713.  * is.mode2 = memory allocation mode for mal()
  714.  */
  715. void malchm(ce) /* allocate space and protect it */
  716. Pcells  ce;
  717. {   /* is.sval = requested size of block, is.sval2 = flawed size of block */
  718.     /* is.sval3 = suggested address, & returned address */
  719.     /* is.dreg = location of block, is.mode2 = allocation style */
  720.  
  721.     if (!(is.sval2 = mal(ce,&is.sval3,is.sval,is.mode2)))
  722.     {   SetFlag(ce);
  723.         return ;
  724.     }
  725.     *(is.dreg) = is.sval3;
  726.  
  727.     /* is.sval3 = location of chmoded block */
  728.     /* is.sval2 = size of chmoded block */
  729.     /* is.mode  = chmod mode, unix notation, e.g. 7 = full protection */
  730.  
  731.     if (chmode(ce,is.sval3,is.sval2,is.mode)) /* could be MemModeProt */
  732.         SetFlag(ce);
  733.     else ce->c.fl = 0;
  734. #ifdef HSEX
  735.     if (DoMate())
  736.        SetXover(ce);
  737.     else
  738.        ce->d.x_over_addr = ce->d.mate_addr = 0;
  739. #endif /* ifdef HSEX */
  740. }
  741.  
  742. /* void divide(ce) cell division
  743.  * is.sval  = offset of IP into daughter's genome
  744.  * is.sval2 = eject genome from soup = 0, 1 = leave in soup
  745.  * is.mode  = divide mode (3 steps)
  746.  */
  747. void divide(ce) /* cell division */
  748. Pcells  ce;
  749. {   Pcells nc;           /* pointer to the new cell */
  750.     I32s  i, j, found = 0;
  751.     CellInd  ni;
  752.  
  753.     if (ce->md.s < MinCellSize ||
  754.         ce->d.mov_daught < (I32s) (ce->md.s * MovPropThrDiv))
  755.     {   SetFlag(ce);
  756.         return;
  757.     }
  758.     if (DivSameSiz)
  759.     {   if (ce->mm.s != ce->md.s)
  760.         {   SetFlag(ce);
  761.             return;
  762.         }
  763.         if (DivSameGen &&
  764.             !IsSameGen(ce->mm.s, soup + ce->md.p, soup + ce->mm.p))
  765.         {   SetFlag(ce);
  766.             return;
  767.         }
  768.     }
  769.     if (is.sval2) switch (is.mode) {
  770.     case 0:           /* create cpu */
  771.     {   if ((ce->d.ne.a == ce->q.this.a) && (ce->d.ne.i == ce->q.this.i))
  772.             /* if there is no cpu (first call to div 0) */
  773.         {   nc = GetFreeCell();
  774.             nc->ld = 1;
  775.             nc->mm = ce->md;
  776.             nc->d.dm = 1;
  777.             nc->d.genome = soup + nc->mm.p;
  778.             ce->d.ne = nc->q.this;
  779.             nc->c.ip = nc->mm.p;
  780. #if INST == 2
  781.             nc->c.ip += (is.sval % nc->mm.s);
  782.             for (i = 0; i < NUMREG; i++)
  783.                 nc->c.re[i] = ce->c.re[i];
  784. #endif /* INST == 2 */
  785.         }
  786.         else      /* if there is a cpu (second call to div 0) */
  787.         {   nc = &cells[ce->d.ne.a][ce->d.ne.i];
  788.             if (nc->d.is)   /* call to div 0 after call to div 1 */
  789.             {   RmvFrmSlicer(nc);
  790.                 nc->d.is = 0;
  791.             }
  792.             else     /* two sequential calls to div 0, error */
  793.             {   SetFlag(ce);
  794.                  return;
  795.             }
  796.         }
  797.         break;
  798.     }
  799.     case 1:           /* start cpu */
  800.     {   if ((ce->d.ne.a == ce->q.this.a) && (ce->d.ne.i == ce->q.this.i))
  801.             /* if there is no cpu, div 1 before div 0 */
  802.         {   nc = GetFreeCell();
  803.             nc->ld = 1;
  804.             nc->mm = ce->md;
  805.             nc->d.dm = 1;
  806.             nc->d.genome = soup + nc->mm.p;
  807.             ce->d.ne = nc->q.this;
  808.             nc->c.ip = nc->mm.p;
  809. #if INST == 2
  810.             nc->c.ip += (is.sval % nc->mm.s);
  811.             for (i = 0; i < NUMREG; i++)
  812.                 nc->c.re[i] = ce->c.re[i];
  813. #endif /* INST == 2 */
  814.         }
  815.         else     /* if there is already a cpu, make pointers to it */
  816.             nc = &cells[ce->d.ne.a][ce->d.ne.i];
  817.         if (nc->d.is) /* 2nd call to div 1, cpu is already started */
  818.         {   RmvFrmSlicer(nc);
  819.             nc->d.is = 0;
  820.         }
  821.         else    /* not 2nd call to div 1, cpu is not already started */
  822.         {   EntBotSlicer(nc);
  823.             nc->d.is = 1;
  824.         }
  825.         break;
  826.     }
  827.     case 2: /* split cells */
  828.     {   if ((ce->d.ne.a == ce->q.this.a) && (ce->d.ne.i == ce->q.this.i))
  829.             /* if there is no cpu, div 2 before div 0 */
  830.         {   nc = GetFreeCell();
  831.             nc->ld = 1;
  832.             nc->mm = ce->md;
  833.             nc->d.genome = soup + nc->mm.p;
  834.             nc->c.ip = nc->mm.p;
  835. #if INST == 2
  836.             nc->c.ip += (is.sval % nc->mm.s);
  837.             for (i = 0; i < NUMREG; i++)
  838.                 nc->c.re[i] = ce->c.re[i];
  839. #endif /* INST == 2 */
  840.         }
  841.         else
  842.             nc = &cells[ce->d.ne.a][ce->d.ne.i];
  843.         if (!nc->d.is)   /* no slicer, div 2 before div 1 */
  844.         {   EntBotSlicer(nc);
  845.             nc->d.is = 1;
  846.         }
  847.         ce->md.s = ce->md.p = 0;
  848.         ce->d.ne = ce->q.this; /* clean up if div 0 or 1 before 2 */
  849.         nc->d.dm = 0;
  850.         EntBotReaper(nc);
  851.         DownReperIf(ce);
  852.         DivideBookeep(ce, nc);
  853.     }
  854.     } /* switch */
  855. #if INST != 1
  856.     else
  857.         Emigrate(ce);
  858. #endif /* INST != 1 */
  859.     ce->c.fl = 0;
  860. }
  861.  
  862. #if INST != 1
  863.  
  864. void Emigrate(ce)
  865. Pcells  ce;
  866. {   I32s    i;
  867.     FpInst  p = soup + ce->md.p;
  868.  
  869. /* write genome to ejection function here */
  870.  
  871. /* the following code erases the genome from the soup */
  872. #ifdef ERROR
  873.     if (!ce->md.s)
  874.         FEError(-613,EXIT,WRITE, "Tierra Emigrate() error: ce->md.s = 0");
  875. #endif /* ERROR */
  876.     for (i = 0; i < ce->md.s; i++)
  877.         p[i].inst = 0;
  878. #ifdef ERROR
  879.     if (ce->md.p < 0 || ce->md.p >= SoupSize)
  880.     FEError(-613,EXIT,WRITE, "Tierra Emigrate() error: ce->md.p not in soup");
  881. #endif /* ERROR */
  882.     chmode(ce, ce->md.p, ce->md.s, MemModeFree); 
  883.     MemDealloc(ce->md.p, ce->md.s);
  884.     ce->d.mov_daught = 0;
  885.     ce->d.fecundity++;
  886.     ce->md.s = 0;
  887. }
  888.  
  889. #endif /* INST != 1 */
  890.  
  891. Pcells GetFreeCell()
  892. {   Pcells fc;
  893.     I32s       i, j, found = 0;
  894.  
  895.     if (++NumCells > CellsSize - 2)
  896.         CheckCells();
  897.     for (i = 0; i < NumCelAr; i++)  /* find unoccupied cell struct */
  898.     {   for (j = 0; j < CelArSiz; j++)
  899.         {
  900. #ifdef ERROR
  901.             if (i * j >= CellsSize)
  902.                 FEError(-502,EXIT,WRITE, 
  903.                     "Tierra GetFreeCell() error, exiting");
  904. #endif
  905.             if(!cells[i][j].ld)
  906.             {   found = 1;
  907.                 fc = &cells[i][j];
  908.                 break;
  909.             }
  910.         }
  911.         if (found)
  912.             break;
  913.     }
  914.     InitCell(i, j, fc);
  915.     return fc;
  916. }
  917.  
  918. void CheckCells() /* check and adjust memory allocation if necessary */
  919. {   I32s j, oCellsSize = CellsSize;
  920.     Pcells Fp  tcells;
  921.  
  922. #ifdef ERROR
  923.     sprintf(mes[0], "in_div CheckCells: recalloc, NumCells = %ld", NumCells);
  924.     sprintf(Buff, "    old CellsSize = %ld  ", CellsSize);
  925. #endif
  926.     NumCelAr++;
  927.     tcells = (Pcells Fp) trecalloc((I8s Fp) cells,
  928.         (I32u) sizeof(Pcells) * (I32u) NumCelAr,
  929.         (I32u) sizeof(Pcells) * (I32u) (NumCelAr - 1));
  930.     if (tcells)
  931.         cells = tcells;
  932.     else if (cells)
  933.     {   tfree(cells);
  934.         cells = NULL;
  935.         FEError(-503,EXIT,WRITE, 
  936.         "Tierra CheckCells() cells trecalloc error, out of memory, exiting");
  937.     }
  938.     CellsSize = NumCelAr * CelArSiz;
  939.     cells[NumCelAr - 1] = (Pcells) tcalloc(CelArSiz, sizeof(Cell));
  940.     if (cells[NumCelAr - 1] == NULL)
  941.     {   FEError(-504,EXIT,WRITE, 
  942.          "Tierra CheckCells() cells[] tcalloc error, out of memory, exiting");
  943.     }
  944. #ifdef ERROR
  945.     sprintf(mes[1], "%s new CellsSize = %ld", Buff, CellsSize);
  946.     FEMessage(2,mes);
  947. #ifdef __TURBOC__
  948.     sprintf(mes[0], "coreleft = %lu  divide (cells)", coreleft());
  949.     FEMessage(1,mes);
  950. #endif
  951. #endif
  952.     for (j = 0; j < CelArSiz; j++)
  953.         InitCell(NumCelAr - 1, j, &cells[NumCelAr - 1][j]);
  954. }
  955.  
  956. I32s flaw(ce)
  957. Pcells  ce;
  958. {   CountFlaw++;
  959.     if (RateFlaw && CountFlaw >= RateFlaw)
  960.     {   CountFlaw = tlrand() % RateFlaw;
  961.         TotFlaw++;
  962.         ce->d.flaw++;
  963.         if (tcrand() % 2) return 1;
  964.         return -1;
  965.     }
  966.     return 0;
  967. }
  968.  
  969. /* search in specified direction for
  970.  * nop template return address, returns address of instruction following
  971.  * target template, i.e., target + tz
  972.  * NOTE: ce->c.ip must point to the instruction (agent) being executed
  973.  */
  974. I32s ctemplate(f, b, slim, mode, tz, dir, ce)
  975. I32s *f;    /* starting address for forward search */
  976. I32s *b;    /* starting address for backward search */
  977. I32s *slim; /* search limit, and return for distance searched */
  978. I8s  *mode; /* preference for forward (1) or backward (2) target */
  979. I32s tz;    /* template size */
  980. I32s dir;   /* direction of search, f = forward, b = backward, o = out */
  981. Pcells  ce; /* which cell */
  982. {   I32s  o, l = 1, adrt;
  983.     I32s  i = 0, fmatch = 0, bmatch = 0;
  984.     I8s   df, db;
  985.     Pgl   tgl;
  986.  
  987.     if ((tz < MinTemplSize) || (tz > SoupSize))
  988.     {   adrt = -1;
  989.         *mode = 0;
  990.         goto finish;
  991.     }
  992.     if ((I8s) dir == 'o')      /* both directions */
  993.         df = db = 1;
  994.     else if ((I8s) dir == 'f') /* forward only */
  995.     {   df = 1;
  996.         db = 0;
  997.     }
  998.     else if ((I8s) dir == 'b') /* backwards only */
  999.     {   df = 0;
  1000.         db = 1;
  1001.     }
  1002.     o = ad(ce->c.ip + 1);
  1003.     while (1) {
  1004.     while (1) /* this skips sections of codes that are not templates (NOPs) */
  1005.     {
  1006. #if PLOIDY == 1
  1007.         if ((df &&               /* forward */
  1008.             (soup[*f].inst == Nop0 || soup[*f].inst == Nop1)
  1009. #ifdef READPROT
  1010.             && (!soup[*f].read || IsInsideCell(ce,*f))
  1011. #endif /* READPROT */
  1012.             )
  1013.          || (db &&           /* backward */
  1014.             (soup[*b].inst == Nop0 || soup[*b].inst == Nop1)
  1015. #ifdef READPROT
  1016.             && (!soup[*b].read || IsInsideCell(ce,*b))
  1017. #endif /* READPROT */
  1018.             ))
  1019. #else /* PLOIDY > 1 */
  1020.         if ((df &&     /* forward */
  1021.             (soup[*f][ce->d.tr].inst == Nop0 || soup[*f][ce->d.tr].inst==Nop1)
  1022. #ifdef READPROT
  1023.             && (!soup[*f][ce->d.tr].read || IsInsideCell(ce,*f))
  1024. #endif /* READPROT */
  1025.             )
  1026.             || (db &&  /* backward */
  1027.             (soup[*b][ce->d.tr].inst == Nop0 || soup[*b][ce->d.tr].inst==Nop1)
  1028. #ifdef READPROT
  1029.             && (!soup[*b][ce->d.tr].read || IsInsideCell(ce,*b))
  1030. #endif /* READPROT */
  1031.             ))
  1032. #endif /* PLOIDY > 1 */
  1033.             break;
  1034.         if (df)
  1035.         {   (*f)++;
  1036.             *f = ad(*f);
  1037.         }
  1038.         if (db)
  1039.         {   (*b)--;
  1040.             *b = ad(*b);
  1041.         }
  1042.         l++;
  1043.         if (l > *slim)   /* if we exceed the search limit abort */
  1044.         {   adrt = -1;
  1045.             *mode = 0;
  1046.             goto finish;
  1047.         }
  1048.     }
  1049.  
  1050.     /* forward */
  1051. #if PLOIDY == 1
  1052.     if (df && (soup[*f].inst == Nop0    /* if NOPs */
  1053.            ||  soup[*f].inst == Nop1))
  1054. #else /* PLOIDY > 1 */
  1055.     if (df && (soup[*f][ce->d.tr].inst == Nop0    /* if NOPs */
  1056.            ||  soup[*f][ce->d.tr].inst == Nop1))
  1057. #endif /* PLOIDY > 1 */
  1058.     {   fmatch = 1;
  1059.         for (i = 0; i < tz; i++)   /* over the full template size */
  1060.         {   
  1061. #if PLOIDY == 1
  1062.             if (soup[ad(o + i)].inst +
  1063.                 soup[ad(*f + i)].inst - NopS
  1064. #ifdef READPROT
  1065.                 || (soup[ad(*f + i)].read
  1066.                 && !IsInsideCell(ce,ad(*f + i)))
  1067. #endif /* READPROT */
  1068. #else /* PLOIDY > 1 */
  1069.             if (soup[ad(o + i)][ce->d.tr].inst +
  1070.                 soup[ad(*f + i)][ce->d.tr].inst - NopS
  1071. #ifdef READPROT
  1072.                 || (soup[ad(*f + i)][ce->d.tr].read
  1073.                 && !IsInsideCell(ce,ad(*f + i)))
  1074. #endif /* READPROT */
  1075. #endif /* PLOIDY > 1 */
  1076.                 )
  1077.             {   fmatch = 0;
  1078.                 break;
  1079.             }
  1080.         }
  1081.     }
  1082.     else fmatch = 0;
  1083.  
  1084.     /* backward */
  1085. #if PLOIDY == 1
  1086.     if (db && (soup[*b].inst == Nop0    /* if NOPs */
  1087.            ||  soup[*b].inst == Nop1))
  1088. #else /* PLOIDY > 1 */
  1089.     if (db && (soup[*b][ce->d.tr].inst == Nop0    /* if NOPs */
  1090.            ||  soup[*b][ce->d.tr].inst == Nop1))
  1091. #endif /* PLOIDY > 1 */
  1092.     {   bmatch = 1;
  1093.         for (i = 0; i < tz; i++)  /* over the full template size */
  1094.         {
  1095. #if PLOIDY == 1
  1096.             if (soup[ad(o + i)].inst +
  1097.                 soup[ad(*b + i)].inst - NopS
  1098. #ifdef READPROT
  1099.                 || (soup[ad(*b + i)].read
  1100.                 && !IsInsideCell(ce,ad(*b + i)))
  1101. #endif /* READPROT */
  1102. #else /* PLOIDY > 1 */
  1103.             if (soup[ad(o + i)][ce->d.tr].inst +
  1104.                 soup[ad(*b + i)][ce->d.tr].inst - NopS
  1105. #ifdef READPROT
  1106.                 || (soup[ad(*b + i)][ce->d.tr].read
  1107.                 && !IsInsideCell(ce,ad(*b + i)))
  1108. #endif /* READPROT */
  1109. #endif /* PLOIDY > 1 */
  1110.                 )
  1111.             {   bmatch = 0;
  1112.                 break;
  1113.             }
  1114.         }
  1115.     }
  1116.     else bmatch = 0;
  1117.  
  1118.     if (fmatch && bmatch)
  1119.     {   if (*mode == 1)
  1120.         {   *f += flaw(ce);
  1121.             adrt = ad(*f + tz);
  1122.             *mode = 3;
  1123.             goto finish;
  1124.         }
  1125.         else if (*mode == 2)
  1126.         {   *b += flaw(ce);
  1127.             adrt = ad(*b + tz);
  1128.             *mode = 3;
  1129.             goto finish;
  1130.         }
  1131.     }
  1132.     else if (fmatch)
  1133.     {   *f += flaw(ce);
  1134.         adrt = ad(*f + tz);
  1135.         *mode = 1;
  1136.         goto finish;
  1137.     }
  1138.     else if (bmatch)
  1139.     {   *b += flaw(ce);
  1140.         adrt = ad(*b + tz);
  1141.         *mode = 2;
  1142.         goto finish;
  1143.     }
  1144.  
  1145.     if (db)      /* increment search pointers, backward and forward */
  1146.     {   (*b)--;
  1147.         *b = ad(*b);
  1148.     }
  1149.     if (df)
  1150.     {   (*f)++;
  1151.         *f = ad(*f);
  1152.     }
  1153.     l++;
  1154.     if (l > *slim)   /* if we exceed the search limit abort */
  1155.     {   adrt = -1;
  1156.         *mode = 0;
  1157.         goto finish;
  1158.     }
  1159.     }  /* outermost while(1) */
  1160. finish:
  1161.     *slim = l;
  1162.     if (1 && WatchTem)
  1163.     tgl = sl[ce->d.gen.size]->g[ce->d.gi];
  1164.     if (1 && WatchTem && adrt >= 0 && !ce->d.flaw && !ce->d.mut &&
  1165.         ce->mm.p <= ce->c.ip && ce->c.ip < (ce->mm.p + ce->mm.s) &&
  1166.         IsBit(tgl->bits, 0))
  1167.     GenExTemp(ad(adrt - tz), ce, tz);
  1168.     return adrt;  /* address of instruction following target template */
  1169. }
  1170.  
  1171. #ifdef FUTURE
  1172.  
  1173. I32s template(f, b, slim, tz, dir, mode, ce)
  1174.  /* search in specified direction for */
  1175.  /* nop template return address, returns address of instruction following */
  1176.  /* target template, i.e., target + tz */
  1177.  /* NOTE: ce->c.ip must point to the instruction (agent) being executed */
  1178.     I32s f;    /* starting address for forward search */
  1179.     I32s b;    /* starting address for backward search */
  1180.     I32s *slim;
  1181.     I32s tz;  /* template size */
  1182.     I32s dir;  /* direction of search, f = forward, b = backward, o = out */
  1183.     I8s mode; /* match mode: 0 = complement, 1 = direct */
  1184.     Pcells  ce; /* which cell */
  1185. {
  1186.     I32s o, l = 1, adrt;
  1187.     I32s i = 0, match;
  1188.     I8s df, db;
  1189.     Pgl tgl;
  1190.  
  1191.     if ((tz < MinTemplSize) || (tz > SoupSize))
  1192.     {   adrt = -1;
  1193.         goto finish;
  1194.     }
  1195.     if ((I8s) dir == 'o') df = db = 1;       /* both directions */
  1196.     if ((I8s) dir == 'f') /* forward only */
  1197.     {   df = 1;
  1198.         db = 0;
  1199.     }
  1200.     if ((I8s) dir == 'b') /* backwards only */
  1201.     {   df = 0;
  1202.         db = 1;
  1203.     }
  1204.     o = ad(ce->c.ip + 1);
  1205.     while (1) {
  1206.     while (1) /* this skips sections of codes that are not templates (NOPs) */
  1207.     {   
  1208.         if (df && (soup[f][ce->d.tr].inst == Nop0 /* forward */
  1209.                ||  soup[f][ce->d.tr].inst == Nop1))
  1210.         break;
  1211.         else
  1212.         {   f++;
  1213.             f = ad(f);
  1214.         }
  1215.         if (db && (soup[b][ce->d.tr].inst == Nop0 /* backward */
  1216.                ||  soup[b][ce->d.tr].inst == Nop1))
  1217.         break;
  1218.         else
  1219.         {   b--;
  1220.             b = ad(b);
  1221.         }
  1222.     }
  1223.     match = 1;       /* forward */
  1224.     if (df && (soup[f][ce->d.tr].inst == Nop0
  1225.            ||  soup[f][ce->d.tr].inst == Nop1))  /* if NOPs */
  1226.     {   if (!mode)  /* compliment match mode */
  1227.         {   for (i = 0; i < tz; i++) /* over the full template size */
  1228.             {   if (!(soup[ad(o + i)][ce->d.tr].inst   /* if not compl */
  1229.                     - soup[ad(f + i)][ce->d.tr].inst ))
  1230.                 {   match = 0;
  1231.                     break;
  1232.                 }
  1233.             }
  1234.         }
  1235.         else  /* direct match mode */
  1236.         {   for (i = 0; i < tz; i++)  /* over the full template size */
  1237.             {   if (soup[ad(o + i)][ce->d.tr].inst         /* if compl */
  1238.                     - soup[ad(f + i)][ce->d.tr].inst )
  1239.                 {   match = 0;
  1240.                     break;
  1241.                 }
  1242.             }
  1243.         }
  1244.         if (match)
  1245.         {   f += flaw(ce);
  1246.             adrt = ad(f + tz);
  1247.             goto finish;
  1248.         }
  1249.     }
  1250.     match = 1;  /* backward */
  1251.     if (db && (soup[b][ce->d.tr].inst == Nop0
  1252.            ||  soup[b][ce->d.tr].inst == Nop1))  /* if NOPs */
  1253.     {   if (!mode)  /* compliment match mode */
  1254.         {   for (i = 0; i < tz; i++)  /* over the full template size */
  1255.             {   if (!(soup[ad(o + i)][ce->d.tr].inst
  1256.                     - soup[ad(b + i)][ce->d.tr].inst ))
  1257.                 {   match = 0;
  1258.                     break;
  1259.                 }
  1260.             }
  1261.         }
  1262.         else  /* direct match mode */
  1263.         {   for (i = 0; i < tz; i++) /* over the full template size */
  1264.             {   if (soup[ad(o + i)][ce->d.tr].inst
  1265.                     - soup[ad(b + i)][ce->d.tr].inst)
  1266.                 {   match = 0;
  1267.                     break;
  1268.                 }
  1269.             }
  1270.         }
  1271.         if (match)
  1272.         {   b += flaw(ce);
  1273.             adrt = ad(b + tz);
  1274.             goto finish;
  1275.         }
  1276.     }   /* increment search pointers, backward and forward */
  1277.     if (db)
  1278.     {   b--;
  1279.         b = ad(b);
  1280.     }
  1281.     if (df)
  1282.     {   f++;
  1283.         f = ad(f);
  1284.     }
  1285.     l++;
  1286.     if (l > *slim)  /* if we exceed the search limit abort */
  1287.     {   adrt = -1;
  1288.         goto finish;
  1289.     }
  1290.     }
  1291. finish:
  1292.     *slim = l;
  1293.     if (1 && WatchTem)
  1294.     tgl = sl[ce->d.gen.size]->g[ce->d.gi];
  1295.     if (1 && WatchTem && adrt >= 0 && !ce->d.flaw && !ce->d.mut &&
  1296.         ce->mm.p <= ce->c.ip && ce->c.ip < (ce->mm.p + ce->mm.s) &&
  1297.         IsBit(tgl->bits, 0))
  1298.     GenExTemp(ad(adrt - tz), ce, tz);
  1299.     return adrt; /* address of instruction following target template */
  1300. }
  1301.  
  1302. I32s btemplate(f, b, slim, tz, dir, mode, ce)
  1303.  /* search in specified direction for */
  1304.  /* binary template return address, returns address of instruction */
  1305.  /* following target template, i.e., target + tz */
  1306.  /* NOTE: ce->c.ip must point to the instruction (agent) being executed */
  1307.     I32s f;    /* starting address for forward search */
  1308.     I32s b;    /* starting address for backward search */
  1309.     I32s *slim;
  1310.     I32s tz;  /* template size */
  1311.     I8s dir;  /* direction of search, f = forward, b = backward, o = out */
  1312.     I8s mode; /* match mode: 0 = complement, 1 = direct */
  1313.     Pcells  ce; /* which cell */
  1314. {   I32s o, l = 1, adrt;
  1315.     I32s i = 0, match;
  1316.     I32s  fd = 0, bd = 0; /* search distance, forward and backward */
  1317.     I8s df, db;
  1318.     Pgl tgl;
  1319.  
  1320.     if ((tz < MinTemplSize) || (tz > SoupSize))
  1321.     {   adrt = -1;
  1322.         goto finish;
  1323.     }
  1324.     if (dir == 'o') df = db = 1; /* both directions */
  1325.     if (dir == 'f') /* forward only */
  1326.     {   df = 1;
  1327.         db = 0;
  1328.     }
  1329.     if (dir == 'b') /* backwards only */
  1330.     {   df = 0;
  1331.         db = 1;
  1332.     }
  1333.     o = ad(ce->c.ip + 1);
  1334.     while (1) {
  1335.     match = 1;
  1336.     if (df)  /* if direction forwards */
  1337.     {   if (!mode) /* compliment match mode */
  1338.         {   for (i = 0; i < tz; i++) /* for full template size */
  1339.             {   if ((soup[ad(o + i)][ce->d.tr].inst
  1340.                 ^ soup[ad(f + i)][ce->d.tr].inst) == 31)
  1341.                 {   match = 0;
  1342.                     break;
  1343.                 }
  1344.             }
  1345.         }
  1346.         else  /* direct match mode */
  1347.         {   for (i = 0; i < tz; i++) /* for full template size */
  1348.             {   if (soup[ad(o + i)][ce->d.tr].inst
  1349.                     == soup[ad(f + i)][ce->d.tr].inst)
  1350.                 {   match = 0;
  1351.                     break;
  1352.                 }
  1353.             }
  1354.         }
  1355.         if (match)
  1356.         {   f += flaw(ce);
  1357.             adrt = ad(f + tz);
  1358.             goto finish;
  1359.         }
  1360.     }
  1361.     if (db) /* if direction backwards */
  1362.     {   match = 1;
  1363.         if (!mode) /* compliment match mode */
  1364.         {   for (i = 0; i < tz; i++) /* for full template size */
  1365.             {   if ((soup[ad(o + i)][ce->d.tr].inst
  1366.                 ^ soup[ad(b + i)][ce->d.tr].inst) == 31)
  1367.                 {   match = 0;
  1368.                     break;
  1369.                 }
  1370.             }
  1371.         }
  1372.         else  /* direct match mode */
  1373.         {   for (i = 0; i < tz; i++) /* for full template size */
  1374.             {   if (soup[ad(o + i)][ce->d.tr].inst
  1375.                     == soup[ad(b + i)][ce->d.tr].inst)
  1376.                 {   match = 0;
  1377.                     break;
  1378.                 }
  1379.             }
  1380.         }
  1381.         if (match)
  1382.         {   b += flaw(ce);
  1383.             adrt = ad(b + tz);
  1384.             goto finish;
  1385.         }
  1386.     }   /* increment search pointers, backward and forward */
  1387.     if (db)
  1388.     {   b--;
  1389.         b = ad(b);
  1390.     }
  1391.     if (df)
  1392.     {   f++;
  1393.         f = ad(f);
  1394.     }
  1395.     l++;
  1396.     if (l > *slim)
  1397.     {   adrt = -1;
  1398.         goto finish;
  1399.     }
  1400.     }
  1401. finish:
  1402.     *slim = l;
  1403.     if (1 && WatchTem)
  1404.     tgl = sl[ce->d.gen.size]->g[ce->d.gi];
  1405.     if (1 && WatchTem && adrt >= 0 && !ce->d.flaw && !ce->d.mut &&
  1406.         ce->mm.p <= ce->c.ip && ce->c.ip < (ce->mm.p + ce->mm.s) &&
  1407.         IsBit(tgl->bits, 0))
  1408.     GenExTemp(ad(adrt - tz), ce, tz);
  1409.     return adrt; /* address of instruction following target template */
  1410. }
  1411.  
  1412. #endif /* FUTURE */
  1413.  
  1414. /* ------------------------------------------------------------------- */
  1415. #ifdef HSEX
  1416.    /* put this at movii at point of  x over  & at mal */
  1417.  
  1418. I8s FindMate(ce)
  1419. Pcells ce;
  1420. {
  1421. /* search out FORWARD (sorry ) to find cell of roughly the close size
  1422.  * but diff genotype
  1423.  * insert addr into ce->d.mate_addr
  1424.  * if (ce->d.x_over_addr > 0)
  1425.  *    ce->d.mate_addr = me->mm.p;
  1426.  * else
  1427.  *    ce->d.mate_addr = me->mm.p + ce->d.x_over_addr;
  1428.  * if one can't be found, return 0
  1429.  *
  1430.  */
  1431.  
  1432. Pcells me;
  1433. I32s fi,fmasl,ll;
  1434. I8s tmd, fi_not_free=0;
  1435.  
  1436. #ifdef ERROR
  1437. if ((!ce))
  1438.    {
  1439.    FEError(-12666,NOEXIT,NOWRITE,"FindMate - Bad cell passed !\n");
  1440.    return 0;
  1441.    }
  1442. #endif
  1443. /* bi = ad(ce->mm.p -1);   byte before cell */
  1444. fi = ad(ce->mm.p +ce->mm.s+1);  /* byte after cell */
  1445. fmasl = ad( (I32s) ( MateSearchL * AverageSize));
  1446.  
  1447.    while(1)
  1448.       {
  1449.       /* forward */
  1450.       if (!(IsFree(fi)))
  1451.          {
  1452.          fi_not_free =1;
  1453.          WhichCell(fi,&me,&tmd);
  1454.          if ((!MateSearchL) && (me == ce)) return 0;
  1455.          if ((tmd == 'm') &&
  1456.              (me->mm.s >= (ce->mm.s - MateSizeEp)) &&
  1457.              (me->mm.s <= (ce->mm.s + MateSizeEp)))
  1458.              {
  1459.              if (!IsSameGen(ce->mm.s,&soup[ce->mm.p],&soup[me->mm.p]))
  1460.                 {
  1461.                 if(ce->d.x_over_addr < 0)
  1462.                   {
  1463.                   ce->d.mate_addr = me->mm.p;
  1464.                   }
  1465.                 else
  1466.                   {
  1467.                   ce->d.mate_addr = ad(me->mm.p + ce->d.x_over_addr);
  1468.                   }
  1469.                 return 1;
  1470.                 }
  1471.  
  1472.              }
  1473.          }
  1474.  
  1475.       /* not found so inc soup indexs */
  1476.       if(fi_not_free)
  1477.         {
  1478.         fi_not_free=0;
  1479.         fi = ad(me->mm.s+me->mm.p +1);
  1480.         }
  1481.       else fi = ad(fi+MinCellSize -1);
  1482.  
  1483.       /* check to see if we are done */
  1484.       if( fi < ce->mm.p) /* we have rolled of the top */
  1485.         {
  1486.         ll = SoupSize - ce->mm.p + fi;
  1487.         }
  1488.       else
  1489.         {
  1490.         ll = fi - ce->mm.p;
  1491.         }
  1492.       if ((!MateSearchL) && (ll > fmasl)) return 0;
  1493.       }
  1494. }       /* end of FindMate */
  1495.  
  1496. /* have func that chooses mate or not in mal */
  1497. I8s DoMate()
  1498. {
  1499. if ((NumCells) && (MateProb > 0.0 ) && ((tlrand() %101) < (100*MateProb))) 
  1500.    return 1;
  1501. return 0;
  1502. }
  1503. /* then have func that chooses x_over */
  1504. I16s SetXover(ce)
  1505. Pcells ce;
  1506. {
  1507. return (((tlrand() %2) ? 1: -1) *
  1508.         (tlrand() % ((I32s) (MateXoverProp * ce->mm.s)+1)));
  1509. }
  1510.  
  1511. void UseMate(ce)
  1512. Pcells ce;
  1513. {
  1514. if ((( ce->d.x_over_addr > 0) &&                /* second half, ! > x_over */
  1515.      (ce->d.mov_daught < ce->d.x_over_addr)) ||
  1516.     (( ce->d.x_over_addr < 0) &&                /* first half, > x_over */
  1517.      (ce->d.mov_daught > (-1*ce->d.x_over_addr))))
  1518.    {
  1519.    is.sval = ad((is.sval - ce->mm.p) + ce->d.mate_addr);
  1520. #if PLOIDY == 1
  1521.    is.dins = &soup[is.sval];
  1522. #else /* PLOIDY > 1 */
  1523.    is.dins = &soup[is.sval][ce-c.tr];
  1524. #endif /* PLOIDY > 1 */
  1525.    }
  1526. }
  1527.  
  1528. #endif /* ifdef HSEX */
  1529.  
  1530. /* ------------------------------------------------------------------- */
  1531. /* ------------------------------------------------------------------- */
  1532.